/**
 * File Name: Simulator.java
 *
 * Date: 18/12/2009
 *
 * Copyright (c) 2006 Michael LaLena. All rights reserved.  (www.lalena.com)
 * Permission to use, copy, modify, and distribute this Program and its documentation,
 *  if any, for any purpose and without fee is hereby granted, provided that:
 *   (i) you not charge any fee for the Program, and the Program not be incorporated
 *       by you in any software or code for which compensation is expected or received;
 *   (ii) the copyright notice listed above appears in all copies;
 *   (iii) both the copyright notice and this Agreement appear in all supporting documentation; and
 *   (iv) the name of Michael LaLena or lalena.com not be used in advertising or publicity
 *          pertaining to distribution of the Program without specific, written prior permission.
 */
package gui;

import model.*;
import java.awt.*;
import javax.swing.JOptionPane;

/**
 * Deze klasse bevat alles om de applet uit te voeren.
 *
 * @author Michiel Declercq
 * @author Stijn Delbeke
 * @author Dieter Deriemaeker
 * @author Gregory Nickmans
 *
 * @author Michael LaLena
 *
 */
public class Simulator extends java.applet.Applet implements Runnable {

    /**
     * Deze klasse bevat alle dieren, obstakels en stromingen
     */
    Aquarium aquarium;

    /**
     * Zorgt voor het regelmatig updaten van de bewegingen
     */
    Thread thread;

    /**
     * Op deze canvas wordt alles getekend
     */
    SimulatorCanvas canvas;

    /**
     * Dit is de Java Applet init functie
     * Aquarium wordt aangemaakt en objecten worden eraan toegevoegd
     * Venster wordt ingesteld
     */
    @Override
    public void init() {
        aquarium = new Aquarium();
        this.resize(Constanten.CANVAS_WIDTH, Constanten.CANVAS_HEIGHT);
        canvas = new SimulatorCanvas();
        canvas.simulator = this;
        setLayout(new BorderLayout());
        add("Center", canvas);
        canvas.requestFocus();

        aquarium.voegAquariumObjectenToe(Constanten.AANTAL_DIEREN, Constanten.AANTAL_OBSTAKELS);

        aquarium.voegStromingenToe();


    }

    /**
     * Dit is de Java Applet start functie
     * Hier wordt de thread gestart
     */
    @Override
    public void start() {
        if (thread == null) {
            thread = new Thread(this);
            thread.start();
        }
    }

    /**
     * Dit is de Java Applet stop functie
     * Hier wordt de thread gestopt en eventueel een boodschap weergeven als de simulatie afgelopen is.
     */
    @Override
    public void stop() {
        if (thread != null) {
            if (Aquarium.aantalVissen == 0) {
                JOptionPane.showMessageDialog(canvas, "De simulatie is afgelopen", "Einde", JOptionPane.INFORMATION_MESSAGE);
                Aquarium.aantalVissen = -1;
            }
            Stroming.getFlowAreas().clear();
            thread.stop();
            thread = null;

        }
    }

    /**
     * Dit is de Java Applet run functie
     * Deze functie wordt voortdurend herhaald en zorgt ervoor dat 
     * de dieren zich voortbewegen.
     *
     */
    public void run() {
        while (true) {
            if (!(Aquarium.aantalVissen == 0)) {
                aquarium.moveObjects();

                canvas.validate();
                canvas.setVisible(true);
                canvas.repaint();
                canvas.invalidate();
                invalidate();
                repaint();
                this.repaint(canvas.getLocation().x, canvas.getLocation().y, canvas.getSize().width, canvas.getSize().height);
            }
            else {
                stop();
            }
            try {
                //Een korte periode slapen en daarna weer verder gaan
                //Hoe groter deze waarde, hoe minder overhead,
                //maar hoe meer schokken er in de beweging zullen te zien zijn.
                Thread.sleep(Constanten.REFRESH_INTERVAL);
            }
            catch (InterruptedException e) {
            }
        }
    }

    /**
     * Deze klasse zorgt voor de canvas waarop getekend wordt
     */
    class SimulatorCanvas extends Canvas {

        // Image Object voor de canvas
        Image canvasImage;

        // Graphics Object voor de canvas
        Graphics canvasGraphics;

        // Referentie naar de Applet, zodat we aan onze aquarium kunnen
        Simulator simulator;

        //Dit zal al onze tekeningen verzorgen
        DrawObject drawObj = new DrawObject();

        /**
         * Dit is de Java Applet update functie
         * Elke keer deze methode aangeroepen wordt, zal alles getekend worden
         */
        @Override
        public synchronized void update(Graphics g) {
            paint(g);
        }

        /**
         * Dit is de Java Applet paint functie
         * Deze methode tekent alles op de canvas
         */
        @Override
        public synchronized void paint(Graphics g) {
            if (canvas.getWidth() == 0) {
            }
            else {
                if ((canvasImage == null)
                        || (canvasImage.getWidth(this) != canvas.getWidth())
                        || (canvasImage.getHeight(this) != canvas.getHeight())) {
                    if (canvasGraphics != null) {
                        canvasGraphics.dispose();
                    }
                    canvasImage = createImage(canvas.getWidth(), canvas.getHeight());
                    canvasGraphics = canvasImage.getGraphics();
                }

                if (canvasGraphics != null) {
                    canvasGraphics.setColor(Constanten.KLEUR_ACHTERGROND);
                    canvasGraphics.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());

                    for (Stroming s : Stroming.getFlowAreas()) {
                        drawObj.drawStroming(canvasGraphics, s);
                    }

                    for (AquariumObject aqObj : aquarium.getAquariumObjecten()) {
                        if (aqObj instanceof Dier) {
                            drawObj.drawDier(canvasGraphics, (Dier) aqObj);
                        }
                        else if (aqObj instanceof Obstakel) {
                            drawObj.drawObstakel(canvasGraphics, (Obstakel) aqObj);
                        }

                    }

                    canvas.getGraphics().drawImage(canvasImage, 0, 0, this);
                }
            }

        }
    }

}
